﻿using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Xml.Serialization;
using System.IO;
using Emico.Linq.Criterion;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;

namespace Emico.Core.Tests.Criterion
{
    [TestClass]
    public class LambdaExpressionTest
    {
        [TestMethod]
        public void TestSerialize()
        {
            string value = "Value";

            LambdaExpression<TestType, string> e = new LambdaExpression<TestType, string>((x, a0) => x.Name == a0, value);
            using(MemoryStream ms = new MemoryStream())
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(ms, e);

                ms.Position = 0;
                var result = (LambdaExpression<TestType>)bf.Deserialize(ms);

                Assert.AreEqual(value, result.Args[0]);
            }
        }

        [TestMethod]
        public void TestQuery()
        {
            TestType[] data = new TestType[]
            {
                new TestType { Id = 1, Name = "aaabbbcc" },
                new TestType { Id = 2, Name = "xxxaaabcc" },
                new TestType { Id = 3, Name = "xxxaaa" },
                new TestType { Id = 4, Name = "aaa" },
                new TestType { Id = 5, Name = "dddd" },
                new TestType { Id = 6, Name = "eee" }
            };

            LambdaExpression<TestType> e = new LambdaExpression<TestType>(t => t.Name.Contains("aaa"));

            Criteria<TestType> criteria = new Criteria<TestType>(e);
            int count = criteria.AsQueryable(data).Count();
            Assert.AreEqual(4, count);
        }

        [TestMethod]
        public void TestQuery1()
        {
            TestType[] data = new TestType[]
            {
                new TestType { Id = 1, Name = "aaabbbcc" },
                new TestType { Id = 2, Name = "xxxaaabcc" },
                new TestType { Id = 3, Name = "xxxaaa" },
                new TestType { Id = 4, Name = "aaa" },
                new TestType { Id = 5, Name = "dddd" },
                new TestType { Id = 6, Name = "eee" }
            };

            IExpression<TestType> e = new LambdaExpression<TestType>(t => t.Name.Contains("aaa"))
                .Or(t => t.Name =="dddd");

            Criteria<TestType> criteria = new Criteria<TestType>(e);
            int count = criteria.AsQueryable(data).Count();
            Assert.AreEqual(5, count);
        }

        [TestMethod]
        public void TestQuery2()
        {
            TestType[] data = new TestType[]
            {
                new TestType { Id = 1, Name = "aaabbbcc" },
                new TestType { Id = 2, Name = "xxxaaabcc" },
                new TestType { Id = 3, Name = "xxxaaa" },
                new TestType { Id = 4, Name = "aaa" },
                new TestType { Id = 5, Name = "dddd" },
                new TestType { Id = 6, Name = "eee" }
            };
       
            Criteria<TestType> criteria = new Criteria<TestType>();
            int count = criteria.AsQueryable(data).Count();
            Assert.AreEqual(6, count);
        }

        [TestMethod]
        public void TestQuery3()
        {
            TestType[] data = new TestType[]
            {
                new TestType { Id = 1, Name = "aaabbbcc" },
                new TestType { Id = 2, Name = "xxxaaabcc" },
                new TestType { Id = 3, Name = "xxxaaa" },
                new TestType { Id = 4, Name = "aaa" },
                new TestType { Id = 5, Name = "dddd" },
                new TestType { Id = 6, Name = "eee" }
            };

            IExpression<TestType> e = new EmptyExpression<TestType>();
            e = e.And(t => t.Name.Contains("aaa"));

            Criteria<TestType> criteria = new Criteria<TestType>(e);
            int count = criteria.AsQueryable(data).Count();
            Assert.AreEqual(4, count);
        }
    }
}
